{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "deb3ff91-9b41-40cb-a5ad-adf41c19eb05",
   "metadata": {},
   "source": [
    "# 什么是推理（Reasoning）？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93c5c325-ddb2-4c7f-80da-1e49443d97a1",
   "metadata": {},
   "source": [
    "在做出选择或处理问题时，推理是通过使用基于新的或现有信息的逻辑来理性地评价事物的能力。推理使你在决定最佳方案或最能满足你的目标的方案之前，能够平衡两个或多个方案的优点和缺点。它还能帮助你解决困难、处理不确定性、核实索赔，并仔细评估情况，以确保你做出的决定符合你的最佳利益[1]。比如：最近你打算买一台电脑？ 决定之前，首先你会考虑你的预算，查看你预算范围的产品；其次如果你追求颜值，接下来你会考虑电脑的外观，如果你追求性价比，你会更关注电脑的硬件，比如CPU、GPU、内存等；此外还有你的需求（学习or工作），时间紧迫性等等，综合考虑多个因素，最终得出一个最合适的方案。这是人类的一项宝贵的技能，在人类的生活中拥有广泛的应用。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72140b43-5e45-42c2-a68d-77c5b52af71f",
   "metadata": {},
   "source": [
    "![](image/logical-reasoning-overview.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22f59133-90e6-4a4a-918d-321440e358d0",
   "metadata": {},
   "source": [
    "1. 演绎推理（Deductive Reasoning）[[2](https://www.fibonicci.com/logical-reasoning/)]  </br>\n",
    "&emsp;&emsp;一般来说，演绎推理是指使用一组给定的事实或数据，通过逻辑推理来推导出其他事实。演绎推理，也称为三段论，通常的理解包括两个前提，一个大的和一个小的，然后一个逻辑结论，可以用来证明这些新的事实是真实的。  \n",
    "\n",
    "&emsp;&emsp;例如，经典的例子： \n",
    "\n",
    "> 大前提：人类都是凡人  \n",
    "小前提：苏格拉底是人    \n",
    "结论：苏格拉底是凡人       \n",
    "                               \n",
    "&emsp;&emsp;在 \"苏格拉底是人\"（小前提）的具体情况下，对 \"所有的人都是凡人\"（大前提）的一般规则应用演绎法，可以得出结论：\"苏格拉底是凡人\"。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1d7db74-121e-401a-b31f-d577f89c4d68",
   "metadata": {},
   "source": [
    "2. 归纳推理（Inductive Reasoning）[[2](https://www.fibonicci.com/logical-reasoning/)]  </br>\n",
    "&emsp;&emsp;归纳推理是寻找一种模式或趋势，然后对其进行概括。当你对信息进行归纳和推断时，你并不确定这一趋势是否会继续下去，但你假设它会继续下去。因此，你并不确定基于归纳推理的结论会是100%的真实。 \n",
    "        \n",
    "> 一个著名的假说是： \"天鹅都是白的\"\n",
    "\n",
    "&emsp;&emsp;这个结论是在没有观察到任何黑天鹅的情况下从大量的观察中得出的，因此在逻辑上假设黑天鹅不存在。所以，归纳推理是一种有风险的逻辑推理形式，因为从天鹅的例子来看，如果发现了一只黑天鹅，那么结论就很容易不正确了。\n",
    "\n",
    "\n",
    "&emsp;&emsp;在实际能力测试中，另一个常见的归纳推理的例子是数字序列。试着确定模式，归纳和推断，找到该序列的下一个数字。\n",
    "\n",
    "> \"6, 9, 12, 15, ?\"\n",
    "        \n",
    "&emsp;&emsp;这个趋势的逻辑答案似乎是18，但你不可能100%确定，也许这个数字代表的是天或小时或一些你意想不到的怪事，这可能导致推断出的结果不同。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e5dad56-f6bf-487e-8c6c-fed5cf01ce10",
   "metadata": {},
   "source": [
    "3. 溯因推理（Abductive reasoning）[[2](https://www.fibonicci.com/logical-reasoning/)]  \n",
    "\n",
    "&emsp;&emsp;溯因推理与归纳推理有些类似。它最早是由“猜测”一词引入的，因为这里得出的结论是基于概率的。在归纳推理中，人们假定最合理的结论也是正确的。 \n",
    "\n",
    "&emsp;&emsp;例如：\n",
    "\n",
    "> 大前提：罐子里装满了黄色的弹珠   \n",
    "小前提：鲍勃手里有一颗黄色的弹珠   \n",
    "结论：鲍勃手中的黄色弹珠是从罐子里拿出来的。 \n",
    "\n",
    "&emsp;&emsp;通过溯因推理，鲍勃从罐子里拿走黄色弹珠的可能性是合理的，然而这纯粹是基于推测。黄色弹珠可能是任何人送给鲍勃的，也可能是鲍勃在商店里买的黄色弹珠。因此，从“装满黄色大理石的罐子”的观察中推断出鲍勃拿走了黄色大理石，可能会导致一个错误的结论。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9e18ca0-49e3-4db6-8b00-f92a11002f49",
   "metadata": {},
   "source": [
    "![](image/major-exteriors-of-brain.png)\n",
    "\n",
    "&emsp;&emsp;从上述推理来看，人脑的大脑皮层对许多认知和感觉功能都至关重要，人类推理的过程和大脑皮层的活动密切相关。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80733fa1-09b3-4819-a381-0c45d5c44e38",
   "metadata": {},
   "source": [
    "&emsp;&emsp;近年来，大型语言模型（Large Language Model，LLM）发展迅速，100B甚至更大参数规模的语言模型出现，它们已经在情感分析和机器翻译等任务上取得了十分优异的表现。特别的，去年12月ChatGPT横空出世，凭借其强大的能力和普遍的适用性直接破圈，引起了各行各业的人群关注。ChatGPT是生成式预训练 Transformer（GPT）语言系列模型中的一个成员。OpenAI在GPT-3改进版“GPT-3.5”上进行微调得到的。ChatGPT拥有非常强大的能力，甚至有研究者发现ChatGPT能够以9岁儿童的能力通过思维理论测试。那么，ChatGPT有多强大呢？它在推理这类任务上有着怎样的表现呢？有没有方法能进一步激发或是增强其处理复杂任务的能力？ChatGPT这种生成模型是否具有大脑的功效呢？不同功能区是如何划分呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0725449-8065-476e-89a8-be01f69d0898",
   "metadata": {},
   "source": [
    "# GPT推理应用"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a98382e6-a7ea-42d8-ad91-9de92c5057a6",
   "metadata": {},
   "source": [
    "Chatgpt一个对话的API调用包含两个必要的**输入**：\n",
    "\n",
    "- model: 使用的模型名称（例如：gpt-3.5-turbo, gpt-4, gpt-4-0314）。本文写作之初，OpenAI并未公布gpt-4, gpt-4-0314，为测试方便，结果均为gpt-3.5-turbo（也就是我们最常用的ChatGPT的版本）的输出。\n",
    "- message: 一个消息对象的列表，每个对象有两个必要的字段：\n",
    "    - role: 信使的角色，包括：system、user，or assistant)\n",
    "        - system：系统角色，用来给assistant设置一些高级的指导或者行为，比如“You are a helpful assistant.”2。\n",
    "        - user：用户角色，用来给assistant提供指令或者问题，比如“tell me a joke”2。user可以是应用的最终用户，也可以是开发者。\n",
    "        - assistant：助手角色，用来给user回复消息或者完成任务，比如“Why did the chicken cross the road?”2。assistant的消息可以帮助存储之前的对话历史，也可以被开发者修改来调整模型的预期行为。\n",
    "    - content: 信息的内容，例如: 给我写一首美丽的诗"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a01fadf-55c0-4f5b-8fec-ff330f1ed987",
   "metadata": {},
   "source": [
    "**响应**对象包括下面几个字段：\n",
    "\n",
    "- id: 请求的ID\n",
    "- object: 返回的对象的类型（如chat.completion）\n",
    "- created: 请求的时间戳\n",
    "- model: 用于生成回复的模型的全名\n",
    "- usage: 用于生成回复的token数量，包括提示、完成和总数。\n",
    "- choices: 完成对象的列表(只有一个，除非你设置n大于1)\n",
    "    - message: 由模型生成的消息对象，包括角色和内容\n",
    "    - finish_reason: ：模型停止生成文本的原因（要么是停止，要么是长度，如果达到max_tokens的限制）\n",
    "    - index: 选择列表中的完成度的索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "720d61fc-68c9-42ec-9ec3-735f73708c77",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import openai\n",
    "# 导入自己的API key\n",
    "openai.api_key = os.environ.get(\"OPENAI_API_KEY\")\n",
    "MODEL = \"gpt-3.5-turbo\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "202edd82-a740-4014-b05e-93178777780a",
   "metadata": {},
   "source": [
    "## 演绎推理（Deductive Reasoning）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9f82dfd3-1939-4127-a29e-a0e82854b418",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "苏格拉底是凡人。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"大前提：人类都是凡人 \\n \\\n",
    "                                     小前提：苏格拉底是人 \\n \\\n",
    "                                     结论：\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "017a939c-7210-4eca-8ffe-ae9340915f0f",
   "metadata": {},
   "source": [
    "## 归纳推理（Inductive Reasoning）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3d9bc020-6f0f-485c-9a7c-cfdff6731b86",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "是甜的。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"西瓜是甜的，香瓜是甜的，所以叫“瓜”的蔬果都应该 \\n \\\n",
    "                                     结论：\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1d9458dd-7ae2-40f1-9ff4-3a73b5cb2bc1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "18\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"6, 9, 12, 15, ? \\n \\\n",
    "                                     结论：\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3f6508e-6037-4c96-be81-2c2908d5004a",
   "metadata": {},
   "source": [
    "## 溯因推理（Abductive reasoning）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3863a3ff-0359-4e69-8f33-18a269ee3d73",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "无法确定，因为罐子里装满了黄色的弹珠，鲍勃手里的黄色弹珠可能来自罐子里，也可能来自其他地方。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"大前提：罐子里装满了黄色的弹珠  \\n \\\n",
    "                                    小前提：鲍勃手里有一颗黄色的弹珠  \\n \\\n",
    "                                    问题：鲍勃手里的弹珠来自哪里？\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "78b7b8fd-b591-4f3e-9d05-47a48b0ef79f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "可能是电源线路接触不好导致的。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"如果电源线路接触不好，那么日光灯熄灭；日光灯熄灭，\\n \\\n",
    "                                     所以: \"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80913df8-3860-44d8-890c-0690b76276d9",
   "metadata": {},
   "source": [
    "## 三者区别"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06cc03e4-06f4-44a0-aff3-fed4cb4320c6",
   "metadata": {},
   "source": [
    "![](image/resoning.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36e16711-ba5b-4fd1-8640-584764e80c59",
   "metadata": {},
   "source": [
    "# 调用ChatPT的推理能力"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f164615-bd00-47bb-b3b7-a17271bd49bb",
   "metadata": {},
   "source": [
    "如果我们让ChatGPT回答一个的问题，简单一点的ChatGPT紧凭“直觉”（这里的直觉可以理解就是“一下子”得到）就可以回答，但当遇到一些较为复杂的问题时，ChatGPT一下子就无法很好的胜任了，可能需要一下子＋一下子，两下子才可以，甚至需要多下子才能完成。总结下来就是：面对复杂问题，人需要思考，ChatGPT也不例外，它也需要思考。如何让ChatGPT使用\"多下子\"的能力呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9c41539-497e-40e6-9d1d-0855cc332481",
   "metadata": {},
   "source": [
    "&emsp;&emsp;可以从以下几个方面入手：\n",
    "\n",
    "1. 问题结束，加上让它思考的魔法语句，比如：\"**Let's think step by step.**\" , 让ChatGPT思考起来 \n",
    "2. 给一个或者几个例子，让ChatGPT类比学习一下  \n",
    "3. 让ChatGPT使用多种思路回答，最后综合一下，优中选优"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7248361b-dfb1-4db2-bda9-b19d61fbd5b9",
   "metadata": {},
   "source": [
    "![](image/think.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "325becc8-d39c-4260-b29b-2e3a6bfc953a",
   "metadata": {},
   "source": [
    "## LLM推理求鼓励，请告诉ChatGPT去思考——Let's think step by step(Zero-shot-COT"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8e3c677-2c6a-4c1d-ad2f-39be401b9caa",
   "metadata": {},
   "source": [
    "零样本思维链（Zero-shot-CoT）的提示，来自论文 Takeshi Kojima et al. in 2022，以一种极其简单的方式，即在答案前加上 \"Let's think step by step\"，促使模型进行思考，进而推理出正确的答案。\n",
    "![zero-shot reasoning example](image/0-COT.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc999cfc-b1d0-4ac6-8695-39031fa7aba8",
   "metadata": {},
   "source": [
    "一个完整的Zero-shot-CoT过程涉及两个独立步骤：第一步，进行推理；第二步，提取答案。首先使用第一个“推理”提示，从语言模型中提取完整的推理路径，然后使用第二个“答案”提示，从推理文本中提取正确格式的答案。\n",
    "![zero-shot reasoning example](image/zero-shot_reasoners_fig2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bb58a14-e4e1-4fed-a0f1-76279f513d07",
   "metadata": {},
   "source": [
    "案例：\n",
    "\n",
    "问题：\n",
    "\n",
    "&emsp;&emsp;用一只水桶装水，把水加到原来的2倍，连桶重10千克，如果把水加到原来的5倍，连桶重22千克。桶里原有水多少千克？\n",
    "\n",
    "答案：\n",
    "\n",
    "（22-10）÷（5-2）=12÷3=4（千克）\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4bc8433f-ad23-48fa-9afd-61b14db5aaa7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "设原来水的重量为x千克，则加水后水的重量为2x千克，加水前桶的重量为10-2x千克，加水后桶的重量为22-5x千克。\n",
      "\n",
      "根据题意，有以下两个方程：\n",
      "\n",
      "2x + 10 - 2x = 22 - 5x\n",
      "\n",
      "化简得：3x = 12\n",
      "\n",
      "解得：x = 4\n",
      "\n",
      "因此，桶里原有水的重量为4千克。\n"
     ]
    }
   ],
   "source": [
    "# 直接问ChatGPT版本\n",
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"用一只水桶装水, 把水加到原来的2倍, 连桶重10千克, 如果把水加到原来的5倍, 连桶重22千克。桶里原有水多少千克?\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a72d77d2-6a9e-494d-a237-76d51b253d96",
   "metadata": {},
   "source": [
    "使用Zero-shot COT推理:\n",
    "\n",
    "第1步，获取完整推理步骤："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "af5f3e28-303a-425c-a283-cecef95b3065",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "设原来桶里的水重x千克，桶本身重y千克，则有：\n",
      "\n",
      "第一步：加到原来的2倍\n",
      "\n",
      "桶里的水重变成2x千克，桶本身重不变，总重为2x+y+10\n",
      "\n",
      "第二步：加到原来的5倍\n",
      "\n",
      "桶里的水重变成5x千克，桶本身重不变，总重为5x+y+22\n",
      "\n",
      "根据以上两个式子，我们可以列出一个方程组：\n",
      "\n",
      "2x+y+10=2(1x+y)  （加到原来的2倍）\n",
      "\n",
      "5x+y+22=5(1x+y)  （加到原来的5倍）\n",
      "\n",
      "化简得：\n",
      "\n",
      "x=12\n",
      "\n",
      "因此，原来桶里的水重12千克。\n"
     ]
    }
   ],
   "source": [
    "# example without a system message\n",
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"用一只水桶装水, 把水加到原来的2倍, 连桶重10千克, 如果把水加到原来的5倍, 连桶重22千克。桶里原有水多少千克? Let's think step by step.\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "666b8b3b-47a4-4943-954e-bbc37fbd2a17",
   "metadata": {},
   "source": [
    "第2步：提取答案"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "381ae20c-d76a-4004-a32d-062620013e2e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"用一只水桶装水, 把水加到原来的2倍, 连桶重10千克, 如果把水加到原来的5倍, 连桶重22千克。桶里原有水多少千克? Let's think step by step.\"},\n",
    "        {\"role\": \"assistant\", \"content\": \"设原来桶里的水重x千克，桶本身重y千克，则有： \\n \\\n",
    "                                        第一步：加到原来的2倍 \\n \\\n",
    "                                        桶里的水变成2x千克，桶本身重y+10千克。 \\n \\\n",
    "                                        第二步：加到原来的5倍 \\n \\\n",
    "                                        桶里的水变成5x千克，桶本身重y+22千克。 \\n \\\n",
    "                                        根据以上两个式子，我们可以列出一个方程组： \\n \\\n",
    "                                        2x + y + 10 = 5x + y + 22  \\n \\\n",
    "                                        化简得： \\n \\\n",
    "                                        3x = 12 \\n \\\n",
    "                                        x = 4 \\n \\\n",
    "                                        所以，原来桶里的水重4千克。\"},\n",
    "        {\"role\": \"user\", \"content\": \"所以，答案是（阿拉伯数字）：\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09f4fc3e-d3d4-44cc-9f52-9db00267cb29",
   "metadata": {},
   "source": [
    "## 给几个例子，告诉ChatGPT应该这么思考——Chain of Thought Prompting"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28b8756e-3210-4054-bf95-bd79903a5c49",
   "metadata": {},
   "source": [
    "思维链(CoT)提示是一种最近开发的提示方法，旨在鼓励大语言模型解释其推理过程。下图显示了 few shot standard prompt（左）与 COT 过程（右）的比较。\n",
    "![chain of thought example](image/chain_of_thought_fig1.png)\n",
    "\n",
    "CoT的主要思想是，通过向LLM展示一些少量的典范，在样例中解释推理过程，大语言模型在回答提示时也会跟着进行推理。\n",
    "\n",
    "下面我们通过以下例子（本例来源于[增强ChatGPT回答的逻辑性](https://mp.weixin.qq.com/s?__biz=MzI1MTE3MTIwOQ==&mid=2247483750&idx=1&sn=ef559cfaadda6947e99ea0a16e36a69d&chksm=e9f65980de81d09616e4be6d7a46a39c1f878812b247b8a5a4dea7eceade827ea9491b10211d#rd)）来演示一下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f1c54a76-a441-45b3-a0b2-92e0daf63bd5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "奇数有4个：3、35、96、923。\n",
      "偶数有6个：56、40、10、84、32、20。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"在这些数字3、56、35、96、40、10、84、923、32、20 中，有多少个奇数，多少个偶数？\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41edb3fc-f332-49fb-96a2-a2cd23501c08",
   "metadata": {},
   "source": [
    "&emsp;&emsp;正确答案是：3个奇数，7个偶数。这里不知道为什么ChatGPT把96也当成是奇数了，可能觉得96和3相关，其他和三相关的都是奇数，所以把它也列为奇数了？？\n",
    "\n",
    "&emsp;&emsp;下面加上，Let's think step by step，试试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c9c164ef-6587-4d3b-a641-2390b9202c66",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "首先，我们需要知道什么是奇数和偶数。奇数是指不能被2整除的整数，而偶数是指能被2整除的整数。\n",
      "\n",
      "接下来，我们可以逐个检查这些数字，看它们是否是奇数或偶数。 \n",
      "\n",
      "3是奇数，因为它不能被2整除。 \n",
      "\n",
      "56是偶数，因为它能被2整除，即56÷2=28。 \n",
      "\n",
      "35是奇数，因为它不能被2整除。 \n",
      "\n",
      "96是偶数，因为它能被2整除，即96÷2=48。 \n",
      "\n",
      "40是偶数，因为它能被2整除，即40÷2=20。 \n",
      "\n",
      "10是偶数，因为它能被2整除，即10÷2=5。 \n",
      "\n",
      "84是偶数，因为它能被2整除，即84÷2=42。 \n",
      "\n",
      "923是奇数，因为它不能被2整除。 \n",
      "\n",
      "32是偶数，因为它能被2整除，即32÷2=16。 \n",
      "\n",
      "20是偶数，因为它能被2整除，即20÷2=10。 \n",
      "\n",
      "因此，在这些数字中，有5个奇数和5个偶数。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"在这些数字3、56、35、96、40、10、84、923、32、20 中，有多少个奇数，多少个偶数？Let's think step by step.\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8616c0a-c510-4fb1-a1c3-058884e98fe0",
   "metadata": {},
   "source": [
    "“Let's think step by step.”失效了，难道ChatGPT真的就无法处理这种情况了吗？放心，不是的，我们换个手段，给ChatGPT例子学习一下， Make ChatGPT Great Again!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "3efbfb32-f635-42f8-bd45-bb7e0a554c60",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我们一个一个数：\n",
      "             1. 3是奇数，此时累计：偶数0个，奇数1个； \n",
      "             2. 56是偶数，此时累计：偶数1个，奇数1个； \n",
      "             3. 35是奇数，此时累计：偶数1个，奇数2个； \n",
      "             4. 96是偶数，此时累计：偶数2个，奇数2个； \n",
      "             5. 40是偶数，此时累计：偶数3个，奇数2个； \n",
      "             6. 10是偶数，此时累计：偶数4个，奇数2个； \n",
      "             7. 84是偶数，此时累计：偶数5个，奇数2个； \n",
      "             8. 923是奇数，此时累计：偶数5个，奇数3个； \n",
      "             9. 32是偶数，此时累计：偶数6个，奇数3个； \n",
      "             10. 20是偶数，此时累计：偶数7个，奇数3个； \n",
      "             所以，一共有7个偶数，3个奇数。\n"
     ]
    }
   ],
   "source": [
    "response = openai.ChatCompletion.create(\n",
    "    model=MODEL,\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": \"在这些数字 38、31、89、224种，有多少个奇数，多少个偶数？.\"},\n",
    "        {\"role\": \"assistant\", \"content\": \"我们一个一个数：\\n \\\n",
    "            1. 38是偶数，此时累计：偶数1个，奇数0个； \\n \\\n",
    "            2. 31是奇数，此时累计：偶数1个，奇数1个； \\n \\\n",
    "            3. 89是奇数，此时累计：偶数1个，奇数2； \\n \\\n",
    "            4. 224是偶数，此时累计：偶数2个，奇数2个； \\n \\\n",
    "            所以,一共有2个偶数，2个奇数。\"},\n",
    "        {\"role\": \"user\", \"content\": \"在这些数字3、56、35、96、40、10、84、923、32、20 中，有多少个奇数，多少个偶数？\"},\n",
    "    ],\n",
    "    temperature=0,\n",
    ")\n",
    "\n",
    "print(response['choices'][0]['message']['content'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "150357db-94f1-4401-80a4-f9e9ceac89f3",
   "metadata": {},
   "source": [
    "![chain of thought example](image/cot_s.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f1a1f54-29d2-4940-9509-8f80671a4a3b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
